package com.hy.app.utils;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class OpenGlUtils {
    private static final String TAG = "OpenGlUtils";

    public static String readRawShaderFile(Context context, int shareId) {
        InputStream is = context.getResources().openRawResource(shareId);
        BufferedReader br = new BufferedReader(new InputStreamReader(is));

        String line;
        StringBuffer sb = new StringBuffer();
        try {

            while ((line = br.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }

            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 编译顶点着色器
     */
    public static int compileVertexShader(String shaderCode) {
        return compileShader(GLES30.GL_VERTEX_SHADER, shaderCode);
    }

    /**
     * 编译片元着色器
     */
    public static int compileFragmentShader(String shaderCode) {
        return compileShader(GLES30.GL_FRAGMENT_SHADER, shaderCode);
    }

    /**
     * 编译
     *
     * @param type 顶点着色器:GLES30.GL_VERTEX_SHADER
     *             片段着色器:GLES30.GL_FRAGMENT_SHADER
     */
    private static int compileShader(int type, String shaderCode) {
        //创建一个着色器
        int shaderId = GLES30.glCreateShader(type);
        if (shaderId != 0) {
            //加载着色器
            GLES30.glShaderSource(shaderId, shaderCode);
            //编译着色器
            GLES30.glCompileShader(shaderId);
            //检测状态
            int[] compileStatus = new int[1];
            GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
            if (compileStatus[0] == 0) {
                String logInfo = GLES30.glGetShaderInfoLog(shaderId);
                Log.e(TAG, "compileShader: " + logInfo);
                //创建失败
                GLES30.glDeleteShader(shaderId);
                return 0;
            }
            return shaderId;
        }
        //创建失败
        return 0;
    }

    /**
     * 链接着色器
     *
     * @param vertexShaderId   顶点着色器
     * @param fragmentShaderId 片元着色器
     */
    public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
        int programId = GLES30.glCreateProgram();
        if (programId != 0) {
            //将顶点着色器加入到程序
            GLES30.glAttachShader(programId, vertexShaderId);
            //将片元着色器加入到程序
            GLES30.glAttachShader(programId, fragmentShaderId);
            //链接着色器程序
            GLES30.glLinkProgram(programId);
            //检查链接状态
            int[] linkStatus = new int[1];
            GLES30.glGetProgramiv(programId, GLES30.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] == 0) {
                String logInfo = GLES30.glGetProgramInfoLog(programId);
                Log.e(TAG, "linkProgram: " + logInfo);
                //链接失败
                GLES30.glDeleteProgram(programId);
                return 0;
            }
            return programId;
        }
        //链接失败
        return 0;
    }

    public static int loadProgram(String mVertexShader, String mFragShader) {
        int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);

        GLES20.glShaderSource(vshader, mVertexShader);

        GLES20.glCompileShader(vshader);

        int[] status = new int[1];

        GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, status, 0);

        if (status[0] != GLES20.GL_TRUE) {
            throw new IllegalStateException("load vertex raw error :" + GLES20.glGetShaderInfoLog(vshader));
        }


        int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);

        GLES20.glShaderSource(fshader, mFragShader);

        GLES20.glCompileShader(fshader);


        GLES20.glGetShaderiv(fshader, GLES20.GL_SHADER_COMPILER, status, 0);

        if (status[0] != GLES20.GL_TRUE) {
            throw new IllegalStateException("load fragment raw error :" + GLES20.glGetShaderInfoLog(fshader));
        }


        int programeId = GLES20.glCreateProgram();

        GLES20.glAttachShader(programeId, vshader);
        GLES20.glAttachShader(programeId, fshader);

        GLES20.glLinkProgram(programeId);

        GLES20.glGetProgramiv(programeId, GLES20.GL_LINK_STATUS, status, 0);


        if (status[0] != GLES20.GL_TRUE) {
            throw new IllegalStateException("link program:" + GLES20.glGetProgramInfoLog(programeId));
        }

        GLES20.glDeleteShader(vshader);
        GLES20.glDeleteShader(fshader);

        return programeId;

    }

    public static void glGenTextures(int[] textures) {
        GLES20.glGenTextures(textures.length, textures, 0);


        for (int i = 0; i < textures.length; i++) {
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i]);


            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);


            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);

            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

        }
    }


    public static void copyAssets2SdCard(Context context, String src, String dst) {
        try {

            File file = new File(dst);
            if (!file.exists()) {
                InputStream is = context.getAssets().open(src);
                FileOutputStream fos = new FileOutputStream(file);
                int len;
                byte[] buffer = new byte[2048];
                while ((len = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, len);
                }
                is.close();
                fos.close();

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
